﻿using LitJson;
using MvCameraControl;
using OCR.Config;
using OCR.Function;
using OCR.SystemThread;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace OCR.SettingsForm
{
    public partial class MultipleRectTemplate_Form : Form
    {
        public static List<List<string>> infosList = new List<List<string>>();
        public static List<List<bool>> insideList = new List<List<bool>>();
        public static List<List<List<Point>>> finalPointlists = new List<List<List<Point>>>();

        public static Bitmap saveBitmap;

        private List<Rectangle> rectangles = new List<Rectangle>();
        private bool isDrawing = false;
        private Point startPoint = Point.Empty;
        Rectangle rect = new Rectangle();
        Rectangle currRect = new Rectangle();

        public static List<List<Point>> pointsList = new List<List<Point>>();

        public static List<List<Point>> finalPointsList = new List<List<Point>>();
        public static List<string> mainInfos = new List<string>();

        public static bool isLocalImg = false;
        public static bool isGetImg = false;

        public static Bitmap cameraRecvBitmap;

        public static Image rectBitmap;
        public MultipleRectTemplate_Form()
        {
            InitializeComponent();
        }

        private void MultipleRectTemplate_Form_Load(object sender, EventArgs e)
        {
            //Console.OutputEncoding = Encoding.UTF8;

            //AlgorithmModule_GPU.CreateInstance();

            //SetTemplateImgPath_Config();
            //SetTem_RectMaxCount_Config();

            RectMaxCountUpdown.Value = LocalInfo.Tem_RectMaxCount;


            MultiTemplatePb.SizeMode = PictureBoxSizeMode.Zoom;

            LocalTemplateSingleInfos_Config.LocalTemplateSingleInfosInitial();

            isGetImg = false;
            isLocalImg = false;

            if (File.Exists(LocalInfo.Tem_ImgPath))
            {
                saveBitmap = (Bitmap)Image.FromFile(LocalInfo.Tem_ImgPath);
                ClearRect();

                //MultiTemplatePb.Image = AlgorithmModule_GPU.RectPoints((Bitmap)MultiTemplatePb.Image, LocalTemplateSingleInfos_Config.rectangles);
                //rectangles = LocalTemplateSingleInfos_Config.rectangles;
                //RectDrawStringNoDouble();
            }
            else
            {
                MessageBox.Show("不存在本地模板图片,请创建模板");
                LocalInfo.Tem_ImgPath = Application.StartupPath + "\\TemplateInput\\OriginBlack.bmp";
                LocalInfo.Tem_ImgPath_Config_InfoUpdate();
                saveBitmap = (Bitmap)Image.FromFile(LocalInfo.Tem_ImgPath);
                ClearRect();
            }

            //AlgorithmModule_GPU.ImageHandleV2_ByteArray(saveBitmap);

            //MultiTemplatePb.Image = AlgorithmModule_GPU.RectPoints1(saveBitmap, AlgorithmModule_GPU.pointsList, AlgorithmModule_GPU.currConfigs);

            //pointsList = AlgorithmModule_GPU.pointsList;

            //for (int i = 0; i < LocalInfo.Tem_RectMaxCount; i++)
            //{
            //    infosList.Add(new List<string>());
            //    insideList.Add(new List<bool>());
            //    finalPointlists.Add(new List<List<Point>>());
            //}

            PicStartPos = MultiTemplatePb.Location;
            PicSize = MultiTemplatePb.Size;
            MultiTemplatePb.MouseWheel += new MouseEventHandler(MultiTemplatePb_MouseWheel);
        }
        //pictureBox1的初始位置
        private Point PicStartPos;
        //pictureBox1的初始大小
        private Size PicSize;
        //鼠标滚轮缩放图片的增量值
        private int ZoomStep = 20;
        private void MultiTemplatePb_MouseWheel(object sender, MouseEventArgs e)
        {
            if (MultiTemplatePb.Image == null) return;
            Console.WriteLine("ZoomStep--------------" + ZoomStep);
            PictureBox pbox = MultiTemplatePb;
            int x = e.Location.X;
            int y = e.Location.Y;
            int ow = pbox.Width;
            int oh = pbox.Height;
            int VX, VY;  //因缩放产生的位移矢量

            int ow1 = rect.Width;
            int oh1 = rect.Height;
            int VX1, VY1;  //因缩放产生的位移矢量
            if (e.Delta > 0)
            {
                if (pbox.Width >= 1624)
                    return;

                pbox.Width = 2 * pbox.Width;
                pbox.Height = 2 * pbox.Height;
                PropertyInfo pInfo = pbox.GetType().GetProperty("ImageRectangle", BindingFlags.Instance | BindingFlags.NonPublic);
                Rectangle rect = (Rectangle)pInfo.GetValue(pbox, null);
                //第3步
                pbox.Width = rect.Width;
                pbox.Height = rect.Height;

                //this.rect.Width = pbox.Width/2;
                //this.rect.Height = pbox.Height/2;
            }
            if (e.Delta < 0)
            {
                //防止一直缩成负值
                if (pbox.Width <= 812)
                    return;

                pbox.Width = pbox.Width / 2;
                pbox.Height = pbox.Height / 2;
                PropertyInfo pInfo = pbox.GetType().GetProperty("ImageRectangle", BindingFlags.Instance |
                 BindingFlags.NonPublic);
                Rectangle rect = (Rectangle)pInfo.GetValue(pbox, null);
                pbox.Width = rect.Width;
                pbox.Height = rect.Height;
            }
            if (e.Delta > 0) //放大
            {
                ////第1步
                //pbox.Width += ZoomStep;
                //pbox.Height += ZoomStep;
                ////第2步
                //PropertyInfo pInfo = pbox.GetType().GetProperty("ImageRectangle", BindingFlags.Instance | BindingFlags.NonPublic);
                //Rectangle rect = (Rectangle)pInfo.GetValue(pbox, null);
                ////第3步
                //pbox.Width = rect.Width;
                //pbox.Height = rect.Height;

                //this.rect.Width -= ZoomStep;
                //this.rect.Height -= ZoomStep;



                //Console.WriteLine(string.Format("宽：{0}，高：{1}",pbox.Width,pbox.Height));
            }
            if (e.Delta < 0) //缩小
            {
                ////防止一直缩成负值
                //if (pbox.Width < 300)
                //    return;

                //pbox.Width -= ZoomStep;
                //pbox.Height -= ZoomStep;
                //PropertyInfo pInfo = pbox.GetType().GetProperty("ImageRectangle", BindingFlags.Instance |
                // BindingFlags.NonPublic);
                //Rectangle rect = (Rectangle)pInfo.GetValue(pbox, null);
                //pbox.Width = rect.Width;
                //pbox.Height = rect.Height;
            }

            //第4步，求因缩放产生的位移，进行补偿，实现锚点缩放的效果
            VX = (int)((double)x * (ow - pbox.Width) / ow);
            VY = (int)((double)y * (oh - pbox.Height) / oh);
            pbox.Location = new Point(pbox.Location.X + VX, pbox.Location.Y + VY);



            Console.WriteLine("pbox.Width:===" + pbox.Width);

            if (pbox.Width == 812)
            {
                //设置坐标
                MultiTemplatePb.Location = PicStartPos;
                //设置控件宽高
                MultiTemplatePb.Size = PicSize;
            }
        }

        public static Image RectPoints(Bitmap bitmap, Rectangle rectangle)
        {
            Bitmap convertedImage = new Bitmap(
            bitmap.Width,
            bitmap.Height,
            PixelFormat.Format32bppArgb);

            using (Graphics g = Graphics.FromImage(convertedImage))
            {
                g.DrawImage(bitmap, 0, 0, bitmap.Width, bitmap.Height);
            }

            Graphics graphics1 = Graphics.FromImage(convertedImage);

            Pen pen = new Pen(Color.Red, 3);

            graphics1.DrawRectangle(pen, rectangle);

            graphics1.Dispose();
            return convertedImage;
        }

        public static Image RectPoints(Bitmap bitmap, List<Rectangle> rectangles)
        {
            Bitmap convertedImage = new Bitmap(
            bitmap.Width,
            bitmap.Height,
            PixelFormat.Format32bppArgb);

            using (Graphics g = Graphics.FromImage(convertedImage))
            {
                g.DrawImage(bitmap, 0, 0, bitmap.Width, bitmap.Height);
            }

            Graphics graphics1 = Graphics.FromImage(convertedImage);

            Pen pen = new Pen(Color.Red, 3);

            for (int i = 0; i < rectangles.Count; i++)
            {
                graphics1.DrawRectangle(pen, new Rectangle(rectangles[i].X * 2, rectangles[i].Y * 2, rectangles[i].Width * 2, rectangles[i].Height * 2));
            }


            graphics1.Dispose();
            return convertedImage;
        }
        private void MultipleRectTemplate_Form_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.D0)
            {
                ClearRect();
            }
        }
        private void MultiTemplatePb_MouseDown(object sender, MouseEventArgs e)
        {
            Console.WriteLine("down_rectangles.Count: " + rectangles.Count);

            if (e.Button == MouseButtons.Left)
            {
                if (rectangles.Count >= LocalInfo.Tem_RectMaxCount)
                {
                    //return;
                    MessageBox.Show("已到画框上限");
                }

                isDrawing = true;
                rect = Rectangle.Empty;
                startPoint = e.Location;
                MultiTemplatePb.Invalidate();

            }
            if (e.Button == MouseButtons.Right)
            {
                //ClearRect();
                ClearLastRect();
            }
        }

        private void MultiTemplatePb_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (isDrawing)
                {
                    //Console.WriteLine("pictureBox1_MouseMove");
                    // Point current = e.Location;
                    // int dx = current.X - startPoint.X;
                    // int dy = current.Y - startPoint.Y;
                    // 根据比例调整宽高
                    // int width, height;
                    // if (Math.Abs(dx) > Math.Abs(dy * ratio))
                    // {
                    //     width = dx;
                    //     height = (int)(width / ratio);
                    // }
                    // else
                    // {
                    //     height = dy;
                    //     width = (int)(height * ratio);
                    // }
                    // 处理反向拖动
                    // int x = startPoint.X;
                    // int y = startPoint.Y;
                    // if (dx < 0) x = current.X;
                    // if (dy < 0) y = current.Y;
                    // 确保宽高为正
                    //width = Math.Abs(width);
                    // height = Math.Abs(height);


                    int x = e.X > startPoint.X ? startPoint.X : e.X;
                    int y = e.Y > startPoint.Y ? startPoint.Y : e.Y;
                    int width = Math.Abs(e.X - startPoint.X);
                    int height = Math.Abs(e.Y - startPoint.Y);


                    rect = new Rectangle(x, y, width, height);
                    currRect = new Rectangle(x * 2, y * 2, width * 2, height * 2);
                    MultiTemplatePb.Invalidate();

                }
            }
        }

        private void MultiTemplatePb_MouseUp(object sender, MouseEventArgs e)
        {
            if (rectangles.Count >= LocalInfo.Tem_RectMaxCount)
            {
                return;
                //MessageBox.Show("已到画框上限");
            }
            if (e.Button == MouseButtons.Left)
            {
                //Console.WriteLine("pictureBox1_MouseUp");
                isDrawing = false;

                if (MultiTemplatePb.Width == 1624)
                {
                    rect = new Rectangle(rect.X / 2, rect.Y / 2, rect.Width / 2, rect.Height / 2);
                }
                else if (MultiTemplatePb.Width == 406)
                {
                    rect = new Rectangle(rect.X * 2, rect.Y * 2, rect.Width * 2, rect.Height * 2);
                }

                Console.WriteLine("rect.X: " + rect.X + " rect.Y: " + rect.Y + " rect.Width: " + rect.Width + " rect.Height: " + rect.Height);
                Console.WriteLine("rect.Location: " + rect.Location + " rect.Right: " + rect.Right + " rect.Left: " + rect.Left + " rect.Top: " + rect.Top + " rect.Bottom: " + rect.Bottom);
                Console.WriteLine("rect.X: " + rect.X * 2 + " rect.Y: " + rect.Y * 2 + " rect.Width: " + rect.Width * 2 + " rect.Height: " + rect.Height * 2);
                //rect = new Rectangle(rect.X * 2, rect.Y * 2, rect.Width * 2, rect.Height * 2);

                MultiTemplatePb.Image = RectPoints((Bitmap)MultiTemplatePb.Image, new Rectangle(rect.X * 2, rect.Y * 2, rect.Width * 2, rect.Height * 2));


                if (rect.X == 0)
                    return;

                rectangles.Add(rect);

                Console.WriteLine("up_rectangles.Count: " + rectangles.Count);

                RectDrawString((Bitmap)MultiTemplatePb.Image);
                
                rect = Rectangle.Empty;
                MultiTemplatePb.Invalidate();
            }
        }

        private void MultiTemplatePb_Paint(object sender, PaintEventArgs e)
        {
            for (int i = 0; i < rectangles.Count; i++)
            {
                //e.Graphics.DrawRectangle(new Pen(Color.Red, 4), rectangles[i]);
            }

            e.Graphics.DrawRectangle(new Pen(Color.Red, 4), rect);
        }
        public void RectDrawString()
        {
            Bitmap img = (Bitmap)MultiTemplatePb.Image;
            using (Graphics g = Graphics.FromImage(img))
            {
                // 创建文本绘制器
                var drawer = new MultiTextDrawer();
                var textItems1 = new List<TextPosition>();
                for (int i = 0; i < rectangles.Count; i++)
                {
                    TextPosition textPosition = new TextPosition((i + 1).ToString(), new PointF(rectangles[i].X * 2, rectangles[i].Y * 2), new Font("微软雅黑", 24), Color.Red);
                    textItems1.Add(textPosition);
                }
                Console.WriteLine("textItems1.Count: " + textItems1.Count);

                // 执行绘制
                Bitmap result = drawer.DrawTexts(img, textItems1);

                MultiTemplatePb.Image = result;
                //result.Save("output.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
            }
        }
        public void RectDrawStringNoDouble()
        {
            Bitmap img = (Bitmap)MultiTemplatePb.Image;
            using (Graphics g = Graphics.FromImage(img))
            {
                // 创建文本绘制器
                var drawer = new MultiTextDrawer();
                var textItems1 = new List<TextPosition>();
                for (int i = 0; i < rectangles.Count; i++)
                {
                    TextPosition textPosition = new TextPosition((i + 1).ToString(), new PointF(rectangles[i].X, rectangles[i].Y-40), new Font("微软雅黑", 24), Color.Red);
                    textItems1.Add(textPosition);
                }
                Console.WriteLine("textItems1.Count: " + textItems1.Count);

                // 执行绘制
                Bitmap result = drawer.DrawTexts(img, textItems1);

                MultiTemplatePb.Image = result;
                //result.Save("output.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
            }
        }

        public void RectDrawString(Bitmap img)
        {
            using (Graphics g = Graphics.FromImage(img))
            {
                // 创建文本绘制器
                var drawer = new MultiTextDrawer();
                var textItems1 = new List<TextPosition>();
                for (int i = 0; i < rectangles.Count; i++)
                {
                    TextPosition textPosition = new TextPosition((i + 1).ToString(), new PointF(rectangles[i].X * 2, rectangles[i].Y * 2 - 40), new Font("微软雅黑", 24), Color.Red);
                    textItems1.Add(textPosition);
                }
                Console.WriteLine("textItems1.Count: " + textItems1.Count);

                // 执行绘制
                Bitmap result = drawer.DrawTexts(img, textItems1);

                MultiTemplatePb.Image = result;
                //result.Save("output.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
            }
        }
        public void Compare(Rectangle rect, List<string> infos, List<bool> inside)
        {
            infos.Clear();
            inside.Clear();
            bool isInsideRect = true;
            Console.WriteLine("识别框个数：" + pointsList.Count);
            Console.WriteLine("rect.X: " + rect.X.ToString() + "  y: " + rect.Y.ToString());
            Console.WriteLine("rect.X: " + (rect.X * 2).ToString() + "  y: " + (rect.Y * 2).ToString());
            foreach (var item in pointsList)
            {
                foreach (var x in item)
                {

                    bool x_Inside = rect.X * 2 <= x.X & x.X <= rect.Right * 2;
                    bool y_Inside = rect.Y * 2 <= x.Y & x.Y <= rect.Bottom * 2;
                    Console.WriteLine("x: " + x_Inside.ToString() + "  y: " + y_Inside.ToString() + "  x&y: " + (x_Inside & y_Inside).ToString());
                    if (!(x_Inside & y_Inside))
                    {
                        isInsideRect = false;
                        break;
                    }
                    else
                    {
                        isInsideRect = true;
                    }
                }


                inside.Add(isInsideRect);
            }
            Console.WriteLine("框选信息个数inside：" + inside.Count);

            for (int i = 0; i < inside.Count; i++)
            {
                if (inside[i])
                {
                    infos.Add(AlgorithmModule_GPU.currConfigs[i].text);
                }
                else
                {
                    //infos.Add(string.Empty);
                }

            }
            Console.WriteLine("框选信息个数：" + infos.Count);
            for (int i = 0; i < infos.Count; i++)
            {
                Console.WriteLine("框选信息内容" + i + "：" + infos[i]);
            }

            for (int i = 0; i < inside.Count; i++)
            {
                Console.WriteLine("当前画框内" + i + "：" + inside[i]);
            }

            for (int i = 0; i < pointsList.Count; i++)
            {
                Console.WriteLine("inside_点数组: " + inside[i]);
                if (inside[i])
                {
                    finalPointsList.Add(pointsList[i]);
                    mainInfos.Add(AlgorithmModule_GPU.currConfigs[i].text);
                }
            }
        }

        public void ClearRect()
        {
            rectangles.Clear();
            rect = Rectangle.Empty;
            MultiTemplatePb.Invalidate();

            if (isGetImg)
            {
                if (isLocalImg)
                {
                    saveBitmap = (Bitmap)Image.FromFile(currPath);

                    Console.WriteLine("saveBitmap:--" + saveBitmap);
                }
                else
                {
                    saveBitmap = (Bitmap)cameraRecvBitmap.Clone();
                }
            }
            else
            {
                saveBitmap = (Bitmap)Image.FromFile(LocalInfo.Tem_ImgPath);
            }


            AlgorithmModule_GPU.ImageHandleV2_Opencv(saveBitmap);
            //AlgorithmModule_GPU.ImageHandleV2_ByteArray((Bitmap)saveBitmap.Clone());

            rectBitmap = AlgorithmModule_GPU.RectPoints1(saveBitmap, AlgorithmModule_GPU.pointsList, AlgorithmModule_GPU.currConfigs);
            MultiTemplatePb.Image = AlgorithmModule_GPU.RectPoints1(saveBitmap, AlgorithmModule_GPU.pointsList, AlgorithmModule_GPU.currConfigs);

            pointsList = AlgorithmModule_GPU.pointsList;

            infosList.Clear();
            insideList.Clear();
            finalPointlists.Clear();


            for (int i = 0; i < LocalInfo.Tem_RectMaxCount; i++)
            {
                infosList.Add(new List<string>());
                insideList.Add(new List<bool>());
                finalPointlists.Add(new List<List<Point>>());
            }
        }

        public void ClearLastRect()
        {
            if (rectangles.Count == 0)
                return;
            rectangles.Remove(rectangles[rectangles.Count-1]);

            if (isGetImg)
            {
                if (isLocalImg)
                {
                    saveBitmap = (Bitmap)Image.FromFile(currPath);

                    Console.WriteLine("saveBitmap:--" + saveBitmap);
                }
                else
                {
                    saveBitmap = (Bitmap)cameraRecvBitmap.Clone();
                }
            }
            else
            {
                saveBitmap = (Bitmap)Image.FromFile(LocalInfo.Tem_ImgPath);
            }

            //AlgorithmModule_GPU.ImageHandleV2_Opencv(saveBitmap);
            //MultiTemplatePb.Image = AlgorithmModule_GPU.RectPoints1(saveBitmap, AlgorithmModule_GPU.pointsList, AlgorithmModule_GPU.currConfigs);

            MultiTemplatePb.Image = RectPoints((Bitmap)rectBitmap, rectangles);

            RectDrawString((Bitmap)MultiTemplatePb.Image);

            rect = Rectangle.Empty;
            MultiTemplatePb.Invalidate();
        }

        private void SetTemplateImgPath_Config()
        {
            string path = Application.StartupPath + "\\Config\\TemplateImgPathConfig.json";
            TemplateImgPathConfig templateImgPathConfig = new TemplateImgPathConfig();
            StreamReader sr = new StreamReader(path);
            string re = sr.ReadToEnd();
            templateImgPathConfig = JsonMapper.ToObject<TemplateImgPathConfig>(re);
            LocalInfo.Tem_ImgPath = templateImgPathConfig.TemplateImgPath;
            Console.WriteLine("LocalInfo.Tem_ImgPath: " + LocalInfo.Tem_ImgPath);
            sr.Dispose();
        }
        private void SetTem_RectMaxCount_Config()
        {
            string path = Application.StartupPath + "\\Config\\Tem_RectMaxCount_Config.json";
            Tem_RectMaxCount_Config tem_RectMaxCount_Config = new Tem_RectMaxCount_Config();
            StreamReader sr = new StreamReader(path);
            string re = sr.ReadToEnd();
            tem_RectMaxCount_Config = JsonMapper.ToObject<Tem_RectMaxCount_Config>(re);
            LocalInfo.Tem_RectMaxCount = int.Parse(tem_RectMaxCount_Config.Tem_RectMaxCount);
            Console.WriteLine("LocalInfo.Tem_RectMaxCount: " + LocalInfo.Tem_RectMaxCount);
            sr.Dispose();
        }
        public string OpenImageWithDialog()
        {
            string path;
            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.Filter = "图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif";
                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    try
                    {
                        Console.WriteLine("openFileDialog.FileName: " + openFileDialog.FileName);
                        //return new Bitmap(openFileDialog.FileName);
                        openFileDialog.Dispose();
                        return openFileDialog.FileName;
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show($"无法打开文件: {ex.Message}");
                        return null;
                    }
                }

            }
            return null;
        }
        public static string currPath;
        public static DateTime grabImgTime;
        private void GetTemplateImgBtn_Click(object sender, EventArgs e)
        {
            isLocalImg = false;
            isGetImg = true;

            if (!CameraReceiveThread.isGrabbing)
            {
                CameraReceiveThread.CameraInitialize();
            }

            if (!CameraReceiveThread.isGrabbing)
                return;

            //相机软触发
            //CameraReceiveThread.device.Parameters.SetEnumValueByString("TriggerSource", "Software");
            //int result1 = CameraReceiveThread.device.Parameters.SetCommandValue("TriggerSoftware");
            //if (result1 != MvError.MV_OK)
            //{
            //    CameraReceiveThread.ShowErrorMsg("Trigger Software Fail!", result1);
            //}


            CameraTriggerThread_MultiTemplate.iCameraTrigger_Step = 3;
            grabImgTime = DateTime.Now;
            Console.WriteLine("模板窗口开始获取图片信息");
            //Thread.Sleep(50);
            Console.WriteLine("软触时间" + DateTime.Now.Millisecond);
            Console.WriteLine("软触一次");


        }
        private void GetLocalImgBtn_Click(object sender, EventArgs e)
        {


            string path = OpenImageWithDialog();

            if (path == null)
                return;
            currPath = path;

            //saveBitmap = (Bitmap)Image.FromFile(path);

            //AlgorithmModule_GPU.ImageHandleV2_ByteArray(saveBitmap);

            //MultiTemplatePb.Image = AlgorithmModule_GPU.RectPoints1(saveBitmap, AlgorithmModule_GPU.pointsList, AlgorithmModule_GPU.currConfigs);

            //pointsList = AlgorithmModule_GPU.pointsList;

            isLocalImg = true;
            isGetImg = true;

            ClearRect();
        }

        private void TemplateCompareBtn_Click(object sender, EventArgs e)
        {
            Console.WriteLine("rectangles.Count:" + rectangles.Count);
            if (rectangles.Count != RectMaxCountUpdown.Value)
            {
                MessageBox.Show("未到画框个数！");
                return;
            }
            if (isGetImg)
            {
                if (isLocalImg)
                {
                    saveBitmap = (Bitmap)Image.FromFile(currPath);
                }
                else
                {
                    saveBitmap = (Bitmap)cameraRecvBitmap.Clone();
                }
            }
            else
            {
                saveBitmap = (Bitmap)Image.FromFile(LocalInfo.Tem_ImgPath);
            }

            finalPointsList.Clear();
            mainInfos.Clear();
            for (int i = 0; i < rectangles.Count; i++)
            {
                Compare(rectangles[i], infosList[i], insideList[i]);
            }


            bool isMultiTemSame = AreArraysContentEqual(infosList);
            Console.WriteLine("isMultiTemSame: "+ isMultiTemSame);
            if (UnifiedTemCB.Checked)
            {
                if (!isMultiTemSame)
                {
                    MessageBox.Show("多个模板需相同");
                    return;
                }
                    
            }

            Image bitmap = AlgorithmModule_GPU.RectPoints1(saveBitmap, finalPointsList, mainInfos);
            RectDrawString((Bitmap)bitmap);

            List<Rectangle> finalRectangles = new List<Rectangle>();
            foreach (var item in rectangles)
            {
                finalRectangles.Add(new Rectangle(item.X * 2, item.Y * 2, item.Width * 2, item.Height * 2));
            }


            MultiTemplatePb.Image = AlgorithmModule_GPU.RectPoints((Bitmap)MultiTemplatePb.Image, finalRectangles);
            //RectDrawString((Bitmap)MultiTemplatePb.Image);
            Console.WriteLine("finalPointsList.Count:" + finalPointsList.Count);
            Console.WriteLine("infosList.mainInfos:" + mainInfos.Count);

            for (int i = 0; i < infosList.Count; i++)
            {
                Console.WriteLine("infosList[i].Count:" + infosList[i].Count);
            }

            MessageBox.Show("识别完成！");
        }

        private void TemplateSaveBtn_Click(object sender, EventArgs e)
        {
            if (rectangles.Count != RectMaxCountUpdown.Value)
            {
                MessageBox.Show("未到画框个数！");
                return;
            }

            // 检查图片是否存在
            if (saveBitmap == null)
            {
                MessageBox.Show("没有可保存的图片！");
                return;
            }

            using (SaveFileDialog saveDialog = new SaveFileDialog())
            {
                // 配置保存对话框
                saveDialog.Title = "保存图片";
                saveDialog.Filter = "BMP 图片|*.bmp|JPEG 图片|*.jpg|PNG 图片|*.png|所有文件|*.*";
                saveDialog.DefaultExt = "jpg";
                saveDialog.AddExtension = true;

                string dateTime = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss-fff");
                saveDialog.FileName = dateTime;

                // 显示对话框并处理结果
                if (saveDialog.ShowDialog() == DialogResult.OK)
                {
                    try
                    {
                        // 根据扩展名选择保存格式
                        string extension = Path.GetExtension(saveDialog.FileName).ToLower();
                        ImageFormat format = ImageFormat.Jpeg; // 默认格式

                        switch (extension)
                        {
                            case ".png":
                                format = ImageFormat.Png;
                                break;
                            case ".bmp":
                                format = ImageFormat.Bmp;
                                break;
                                // JPEG和其他格式使用默认处理
                        }
                        Console.WriteLine(saveDialog.FileName);
                        string targetPath = saveDialog.FileName;

                        using (saveBitmap)
                        {
                            using (var newBitmap = new Bitmap(saveBitmap.Width, saveBitmap.Height))
                            {
                                using (var graphics = Graphics.FromImage(newBitmap))
                                {
                                    graphics.DrawImage(saveBitmap, 0, 0);
                                    saveBitmap.Dispose();
                                    Bitmap finalBitmap = AlgorithmModule_GPU.ConvertTo8bpp(newBitmap);
                                    // 保存图片
                                    finalBitmap.Save(targetPath, format);
                                    //saveBitmap.Save(targetPath);
                                    LocalInfo.Tem_ImgPath = targetPath;
                                    LocalInfo.Tem_ImgPath_Config_InfoUpdate();
                                    MessageBox.Show("图片保存成功！");
                                    graphics.Dispose();
                                    saveBitmap = (Bitmap)Image.FromFile(targetPath);
                                }


                            }
                        }

                        List<LocalTemplateSingleInfo> localTemplateSingleInfos = new List<LocalTemplateSingleInfo>();
                        for (int i = 0; i < infosList.Count; i++)
                        {
                            Console.WriteLine("infosList[i].Count:" + infosList[i].Count);

                            //if (infosList[i].Count > 0) { }

                            LocalTemplateSingleInfo localTemplateSingleInfo = new LocalTemplateSingleInfo();
                            localTemplateSingleInfo.InfoList = infosList[i];
                            localTemplateSingleInfo.rect_X = rectangles[i].X.ToString();
                            localTemplateSingleInfo.rect_Y = rectangles[i].Y.ToString();
                            localTemplateSingleInfo.rect_Width = rectangles[i].Width.ToString();
                            localTemplateSingleInfo.rect_Height = rectangles[i].Height.ToString();
                            localTemplateSingleInfos.Add(localTemplateSingleInfo);
                        }
                        Console.WriteLine("localTemplateSingleInfos.Count:" + localTemplateSingleInfos.Count);

                        LocalTemplateSingleInfos_Config.LocalTemplateInfoSave(localTemplateSingleInfos);

                        LocalTemplateSingleInfos_Config.LocalTemplateSingleInfosInitial();
                        OCR_Form.SetLocalTemplateInfos();

                        OCR_Form.oCR_Form.LocalTemplateInfoLabel.Text = "模板1";
                        OCR_Form.currLocalTemplateInfoIndex = 0;
                        OCR_Form.SetLocalTemplateInfos(OCR_Form.currLocalTemplateInfoIndex);

                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show($"保存失败：{ex.Message}");
                    }
                }
            }
        }


        #region RectMaxCount
        private void RectMaxCountUpdown_ValueChanged(object sender, EventArgs e)
        {
            LocalInfo.Tem_RectMaxCount = (int)RectMaxCountUpdown.Value;
            Console.WriteLine("LocalInfo.Tem_RectMaxCount:" + LocalInfo.Tem_RectMaxCount);
        }

        private void ChangeRectCountBtn_Click(object sender, EventArgs e)
        {
            RectMaxCountUpdown.Enabled = true;

            ChangeRectCountBtn.Enabled = false;
            ConfirmRectCountBtn.Enabled = true;
        }

        private void ConfirmRectCountBtn_Click(object sender, EventArgs e)
        {
            try
            {
                LocalInfo.Tem_RectMaxCount_Config_InfoUpdate();
                RectMaxCountUpdown.Enabled = false;
                ChangeRectCountBtn.Enabled = true;
                ConfirmRectCountBtn.Enabled = false;
                MessageBox.Show("修改成功");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }

            ClearRect();


        }

        #endregion

        private void MultipleRectTemplate_Form_FormClosed(object sender, FormClosedEventArgs e)
        {
            rectBitmap.Dispose();
            saveBitmap.Dispose();
            OCR_Form.multipleRectTemplate_Form = null;
        }
        //判断模板数组中的模板是否完全相同
        bool AreArraysContentEqual(List<List<string>> arrays)
        {
            if(AreAllArraysEmpty(arrays)) return false;

            if (arrays.Count == 0) return false;

            if (arrays.Count == 1) return true;

            // 基准数组频率统计
            var baseFreq = arrays[0]
                .GroupBy(s => s)
                .ToDictionary(g => g.Key, g => g.Count());

            for (int i = 1; i < arrays.Count; i++)
            {
                // 当前数组频率统计
                var currFreq = arrays[i]
                    .GroupBy(s => s)
                    .ToDictionary(g => g.Key, g => g.Count());

                // 比较频率字典
                if (!baseFreq.Count.Equals(currFreq.Count) ||
                    baseFreq.Any(kv => !currFreq.TryGetValue(kv.Key, out int count) || count != kv.Value))
                    return false;
            }
            return true;
        }
        //判断模板数组中的模板是否为空字符串
        bool AreAllArraysEmpty(List<List<string>> arrays)
        {
            return arrays.All(arr =>
                arr != null &&
                arr.All(string.IsNullOrEmpty));
        }


    }
}
